"""
GitCode Pull Request API
"""
from typing import Any, Dict, List, Optional, Union
from datetime import datetime

from ..base.client import BaseAPI


class PullRequestAPI(BaseAPI):
    """Pull Request API"""
    
    async def list_pull_requests(
        self,
        owner: str,
        repo: str,
        state: Optional[str] = None,
        head: Optional[str] = None,
        base: Optional[str] = None,
        sort: Optional[str] = None,
        direction: Optional[str] = None,
        per_page: Optional[int] = None,
        page: Optional[int] = None
    ) -> List[Dict[str, Any]]:
        """
        获取仓库的Pull Request列表
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            state: PR状态 ('open'|'closed'|'all')
            head: 头分支过滤（格式：'user:ref-name'或'ref-name'）
            base: 基分支过滤
            sort: 排序字段 ('created'|'updated'|'popularity'|'long-running')
            direction: 排序方向 ('asc'|'desc')
            per_page: 每页结果数
            page: 页码
            
        Returns:
            Pull Request列表
        """
        params = {
            "state": state,
            "head": head,
            "base": base,
            "sort": sort,
            "direction": direction,
            "per_page": per_page,
            "page": page
        }
        params = {k: v for k, v in params.items() if v is not None}
        
        return await self.request("GET", f"/repos/{owner}/{repo}/pulls", params=params)
    
    async def get_pull_request(self, owner: str, repo: str, pr_number: int) -> Dict[str, Any]:
        """
        获取特定Pull Request的详细信息
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            pr_number: PR编号
            
        Returns:
            Pull Request信息
        """
        return await self.request("GET", f"/repos/{owner}/{repo}/pulls/{pr_number}")
    
    async def create_pull_request(
        self,
        owner: str,
        repo: str,
        title: str,
        head: str,
        base: str,
        body: Optional[str] = None,
        draft: Optional[bool] = None,
        maintainer_can_modify: Optional[bool] = None
    ) -> Dict[str, Any]:
        """
        创建新Pull Request
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            title: PR标题
            head: 源分支
            base: 目标分支
            body: PR内容
            draft: 是否为草稿PR
            maintainer_can_modify: 维护者是否可以修改
            
        Returns:
            创建的Pull Request信息
        """
        data = {
            "title": title,
            "head": head,
            "base": base,
            "body": body,
            "draft": draft,
            "maintainer_can_modify": maintainer_can_modify
        }
        data = {k: v for k, v in data.items() if v is not None}
        
        return await self.request("POST", f"/repos/{owner}/{repo}/pulls", data=data)
    
    async def update_pull_request(
        self,
        owner: str,
        repo: str,
        pr_number: int,
        title: Optional[str] = None,
        body: Optional[str] = None,
        state: Optional[str] = None,
        base: Optional[str] = None,
        maintainer_can_modify: Optional[bool] = None
    ) -> Dict[str, Any]:
        """
        更新Pull Request
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            pr_number: PR编号
            title: 新标题
            body: 新内容
            state: 新状态 ('open'|'closed')
            base: 新目标分支
            maintainer_can_modify: 维护者是否可以修改
            
        Returns:
            更新后的Pull Request信息
        """
        data = {
            "title": title,
            "body": body,
            "state": state,
            "base": base,
            "maintainer_can_modify": maintainer_can_modify
        }
        data = {k: v for k, v in data.items() if v is not None}
        
        return await self.request("PATCH", f"/repos/{owner}/{repo}/pulls/{pr_number}", data=data)
    
    async def list_commits(
        self,
        owner: str,
        repo: str,
        pr_number: int,
        per_page: Optional[int] = None,
        page: Optional[int] = None
    ) -> List[Dict[str, Any]]:
        """
        获取Pull Request的提交列表
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            pr_number: PR编号
            per_page: 每页结果数
            page: 页码
            
        Returns:
            提交列表
        """
        params = {
            "per_page": per_page,
            "page": page
        }
        params = {k: v for k, v in params.items() if v is not None}
        
        return await self.request("GET", f"/repos/{owner}/{repo}/pulls/{pr_number}/commits", params=params)
    
    async def list_files(
        self,
        owner: str,
        repo: str,
        pr_number: int,
        per_page: Optional[int] = None,
        page: Optional[int] = None
    ) -> List[Dict[str, Any]]:
        """
        获取Pull Request的文件列表
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            pr_number: PR编号
            per_page: 每页结果数
            page: 页码
            
        Returns:
            文件列表
        """
        params = {
            "per_page": per_page,
            "page": page
        }
        params = {k: v for k, v in params.items() if v is not None}
        
        return await self.request("GET", f"/repos/{owner}/{repo}/pulls/{pr_number}/files", params=params)
    
    async def check_merged(self, owner: str, repo: str, pr_number: int) -> bool:
        """
        检查Pull Request是否已合并
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            pr_number: PR编号
            
        Returns:
            是否已合并
        """
        try:
            await self.request("GET", f"/repos/{owner}/{repo}/pulls/{pr_number}/merge")
            return True
        except Exception:
            return False
    
    async def merge_pull_request(
        self,
        owner: str,
        repo: str,
        pr_number: int,
        commit_title: Optional[str] = None,
        commit_message: Optional[str] = None,
        merge_method: Optional[str] = None,
        sha: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        合并Pull Request
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            pr_number: PR编号
            commit_title: 合并提交标题
            commit_message: 合并提交消息
            merge_method: 合并方法 ('merge'|'squash'|'rebase')
            sha: 特定的提交SHA
            
        Returns:
            合并结果
        """
        data = {
            "commit_title": commit_title,
            "commit_message": commit_message,
            "merge_method": merge_method,
            "sha": sha
        }
        data = {k: v for k, v in data.items() if v is not None}
        
        return await self.request("PUT", f"/repos/{owner}/{repo}/pulls/{pr_number}/merge", data=data)
    
    async def list_review_comments(
        self,
        owner: str,
        repo: str,
        pr_number: int,
        since: Optional[Union[str, datetime]] = None,
        per_page: Optional[int] = None,
        page: Optional[int] = None
    ) -> List[Dict[str, Any]]:
        """
        获取Pull Request的评审评论
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            pr_number: PR编号
            since: 过滤日期（ISO 8601格式字符串或datetime对象）
            per_page: 每页结果数
            page: 页码
            
        Returns:
            评审评论列表
        """
        # 处理日期
        if isinstance(since, datetime):
            since_str = since.isoformat()
        else:
            since_str = since
            
        params = {
            "since": since_str,
            "per_page": per_page,
            "page": page
        }
        params = {k: v for k, v in params.items() if v is not None}
        
        return await self.request("GET", f"/repos/{owner}/{repo}/pulls/{pr_number}/comments", params=params)
    
    async def create_review_comment(
        self,
        owner: str,
        repo: str,
        pr_number: int,
        body: str,
        commit_id: str,
        path: str,
        position: int
    ) -> Dict[str, Any]:
        """
        创建PR评审评论
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            pr_number: PR编号
            body: 评论内容
            commit_id: 提交SHA
            path: 文件路径
            position: 文件中的位置
            
        Returns:
            创建的评论信息
        """
        data = {
            "body": body,
            "commit_id": commit_id,
            "path": path,
            "position": position
        }
        
        return await self.request("POST", f"/repos/{owner}/{repo}/pulls/{pr_number}/comments", data=data)
    
    async def create_review(
        self,
        owner: str,
        repo: str,
        pr_number: int,
        body: Optional[str] = None,
        event: Optional[str] = None,
        comments: Optional[List[Dict[str, Any]]] = None
    ) -> Dict[str, Any]:
        """
        创建PR评审
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            pr_number: PR编号
            body: 评审评论内容
            event: 评审事件 ('APPROVE'|'REQUEST_CHANGES'|'COMMENT'|'PENDING')
            comments: 评审评论列表
            
        Returns:
            创建的评审信息
        """
        data = {
            "body": body,
            "event": event,
            "comments": comments
        }
        data = {k: v for k, v in data.items() if v is not None}
        
        return await self.request("POST", f"/repos/{owner}/{repo}/pulls/{pr_number}/reviews", data=data)
    
    async def list_reviews(
        self,
        owner: str,
        repo: str,
        pr_number: int,
        per_page: Optional[int] = None,
        page: Optional[int] = None
    ) -> List[Dict[str, Any]]:
        """
        获取Pull Request的评审列表
        
        Args:
            owner: 仓库所有者
            repo: 仓库名称
            pr_number: PR编号
            per_page: 每页结果数
            page: 页码
            
        Returns:
            评审列表
        """
        params = {
            "per_page": per_page,
            "page": page
        }
        params = {k: v for k, v in params.items() if v is not None}
        
        return await self.request("GET", f"/repos/{owner}/{repo}/pulls/{pr_number}/reviews", params=params) 